package com.linyaonan.leetcode.medium._36;

import java.util.HashMap;

/**
 * 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ，验证已经填入的数字是否有效即可。
 *
 * 数字 1-9 在每一行只能出现一次。
 * 数字 1-9 在每一列只能出现一次。
 * 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。（请参考示例图）
 *  
 *
 * 注意：
 *
 * 一个有效的数独（部分已被填充）不一定是可解的。
 * 只需要根据以上规则，验证已经填入的数字是否有效即可。
 * 空白格用 '.' 表示。
 *
 * 输入：board =
 * [["5","3",".",".","7",".",".",".","."]
 * ,["6",".",".","1","9","5",".",".","."]
 * ,[".","9","8",".",".",".",".","6","."]
 * ,["8",".",".",".","6",".",".",".","3"]
 * ,["4",".",".","8",".","3",".",".","1"]
 * ,["7",".",".",".","2",".",".",".","6"]
 * ,[".","6",".",".",".",".","2","8","."]
 * ,[".",".",".","4","1","9",".",".","5"]
 * ,[".",".",".",".","8",".",".","7","9"]]
 * 输出：true
 *
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode.cn/problems/valid-sudoku
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
class Solution {

    /**
     * 思路1：暴力解法：
     * 1. 判断每一行是否有重复
     * 2. 判断每一列是否有重复
     * 3. 判断每一个宫格是否有重复
     * @param board
     * @return
     */
    public boolean isValidSudoku(char[][] board) {
        for (char[] chars : board) {
            if (!checkHang(chars)) {
                return false;
            }
        }
        for (int i = 0; i < 9; i++) {
            if (!checkLie(board, i)) {
                return false;
            }
        }

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (!checkGong(board, i * 3 , (i + 1) * 3, j * 3, (j + 1) * 3)) {
                    return false;
                }
            }
        }

        return true;
    }

    public boolean checkHang(char[] hang) {
        HashMap<Character, Boolean> map = new HashMap<>();
        for (char c : hang) {
            if (c == '.') {
                continue;
            }
            if (map.containsKey(c)) {
                return false;
            } else {
                map.put(c, true);
            }
        }
        return true;
    }

    public boolean checkLie(char[][] board, int lie) {
        HashMap<Character, Boolean> map = new HashMap<>();
        for (int i = 0; i < board.length; i++) {
            char c = board[i][lie];
            if (c == '.') {
                continue;
            }
            if (map.containsKey(c)) {
                return false;
            } else {
                map.put(c, true);
            }
        }
        return true;
    }

    public boolean checkGong(char[][] board, int startHang, int endHang, int startLie, int endLie) {
        HashMap<Character, Boolean> map = new HashMap<>();
        for (int i = startHang; i < endHang; i++) {
            for (int j = startLie; j < endLie; j++) {
                char c = board[i][j];
                if (c == '.') {
                    continue;
                }
                if (map.containsKey(c)) {
                    return false;
                } else {
                    map.put(c, true);
                }
            }
        }
        return true;
    }
}